using System;
using System.Globalization;
using System.Security;
using System.Security.Permissions;
using System.Web;

namespace Salient.Web.Administration
{
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    public sealed class WebAdminModule : IHttpModule
    {
        private const string APP_PATH = "WebAdminApplicationPath";
        private const string APP_PHYSICAL_PATH = "WebAdminPhysicalPath";
        private const string REMOTING_MANAGER = "WebAdminRemotingManager";

        #region IHttpModule Members

        public void Init(HttpApplication application)
        {
            application.Error += (new EventHandler(ApplicationError));
            application.AcquireRequestState += new EventHandler(OnEnter);
        }

        public void Dispose()
        {
        }

        #endregion

        private void ApplicationError(object sender, EventArgs e)
        {
            Exception exception = ((HttpApplication) sender).Server.GetLastError().InnerException;
            HttpContext context = ((HttpApplication) sender).Context;
            string redirectUrl = "~/error.aspx";
            if (String.IsNullOrEmpty(redirectUrl))
            {
                return;
            }

            WebAdminPage.SetCurrentException(context, exception);

            ((HttpApplication) sender).Server.Transfer(String.Format(CultureInfo.InvariantCulture, redirectUrl), true);
        }

        private void OnEnter(Object sender, EventArgs eventArgs)
        {
            var application = (HttpApplication) sender;

            if (!application.Context.Request.IsLocal)
            {
                var securityException =
                    new SecurityException(
                        (string)
                        HttpContext.GetGlobalResourceObject("GlobalResources", "WebAdmin_ConfigurationIsLocalOnly"));
                WebAdminPage.SetCurrentException(application.Context, securityException);
                application.Server.Transfer("~/error.aspx");
            }

            if (application != null)
            {
                SetSessionVariables(application);
            }
            application.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        }

        private void SetSessionVariables(HttpApplication application)
        {
            string queryStringAppPath = string.Empty;
            string queryStringApplicationPhysicalPath = string.Empty;
            string applicationPath = string.Empty;
            string applicationPhysicalPath = string.Empty;
            string setAppPath = string.Empty;
            string setAppPhysPath = string.Empty;

            try
            {
                var permission = new SecurityPermission(PermissionState.Unrestricted);
                permission.Demand();
            }
            catch
            {
                var permissionException =
                    new Exception((string) HttpContext.GetGlobalResourceObject("GlobalResources", "FullTrustRequired"));
                WebAdminPage.SetCurrentException(application.Context, permissionException);
                application.Server.Transfer("~/error.aspx");
            }

            if (application.Context.Request != null)
            {
                queryStringAppPath = (string) application.Context.Request.QueryString["applicationUrl"];
                queryStringApplicationPhysicalPath =
                    (string) application.Context.Request.QueryString["applicationPhysicalPath"];
            }

            if (application.Context.Session != null)
            {
                if (application.Context.Session[APP_PATH] != null)
                {
                    applicationPath = (string) application.Context.Session[APP_PATH];
                }
                if (application.Context.Session[APP_PHYSICAL_PATH] != null)
                {
                    applicationPhysicalPath = (string) application.Context.Session[APP_PHYSICAL_PATH];
                }
            }

            if ((String.IsNullOrEmpty(queryStringAppPath) && applicationPath == null) ||
                (String.IsNullOrEmpty(queryStringApplicationPhysicalPath) && applicationPhysicalPath == null))
            {
                application.Server.Transfer("~/home0.aspx", false);
                return;
            }

            if (!String.IsNullOrEmpty(queryStringAppPath))
            {
                setAppPath = queryStringAppPath;
            }
            else if (!String.IsNullOrEmpty(applicationPath))
            {
                setAppPath = applicationPath;
            }

            if (!String.IsNullOrEmpty(queryStringApplicationPhysicalPath))
            {
                setAppPhysPath = queryStringApplicationPhysicalPath;
            }
            else if (!String.IsNullOrEmpty(applicationPhysicalPath))
            {
                setAppPhysPath = applicationPhysicalPath;
            }

            if (application.Context.Session != null)
            {
                application.Context.Session[APP_PATH] = setAppPath;
                application.Context.Session[APP_PHYSICAL_PATH] = setAppPhysPath;
                application.Context.Session[REMOTING_MANAGER] = new WebAdminRemotingManager(setAppPath, setAppPhysPath,
                                                                                            application.Context.Session);
            }
        }
    }
}